﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Reflection;

namespace ActionModel.Utility
{
	/// <summary>
	/// 数据库操作相关工具
	/// </summary>
	public class DataHelper
	{
		/// <summary>
		/// 提供SQL字符串转义
		/// </summary>
		/// <param name="format">格式字符串</param>
		/// <param name="args">要格式化的对象</param>
		/// <returns></returns>
		public static string FormatSql(string format, params object[] args)
		{
			for (int i = 0; i < args.Length; i++)
			{
				if (args[i] is string)
				{
					args[i] = args[i].ToString().Replace("'", "''");
				}
			}
			return string.Format(format, args);
		}

		public static List<T> FillList<T>(DataTable table) where T : class, new()
		{
			return new List<T>(Fill<T>(table));
		}
		public static T[] Fill<T>(DataTable table) where T : class, new()
		{
			string[] fields = getDataTableFields(table);
			PropertyInfo[] pis = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
			T[] entities = new T[table.Rows.Count];
			for (int i = 0; i < entities.Length; i++)
			{
				entities[i] = FillSinger<T>(table.Rows[i], pis, fields);
			}
			return entities;
		}
		public static T FillSinger<T>(DataRow row) where T : class, new()
		{
			if (row != null)
			{
				string[] fields = getDataTableFields(row.Table);
				PropertyInfo[] pis = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
				return FillSinger<T>(row, pis, fields);
			}
			else
				return null;
		}
		private static T FillSinger<T>(DataRow row, PropertyInfo[] pis, string[] fields) where T : class, new()
		{
			T entity = new T();
			FillEntity<T>(ref  entity, typeof(T), pis, row, fields);
			return entity;
		}
		private static void FillEntity<T>(ref T entity, Type type, PropertyInfo[] pis, DataRow row, string[] fields)
		{
			foreach (PropertyInfo pi in pis)
			{
				if (Array.IndexOf(fields, pi.Name.ToLower()) != -1 && row[pi.Name] != DBNull.Value)
				{
					pi.SetValue(entity, row[pi.Name], null);
				}
			}
			if (typeof(object) != type.BaseType)
			{
				FillEntity<T>(ref  entity, type.BaseType, pis, row, fields);
			}
		}
		private static string[] getDataTableFields(DataTable table)
		{
			string[] fields = new string[table.Columns.Count];
			for (int i = 0; i < fields.Length; i++)
			{
				fields[i] = table.Columns[i].ColumnName.ToLower();
			}
			return fields;
		}


		/// <summary>
		/// 用DataReader填充类型T的实例集
		/// </summary>
		/// <typeparam name="T">实体类型</typeparam>
		/// <param name="reader">只进结果集流</param>
		/// <returns>类型T的实例集</returns>
		public static T[] Fill<T>(IDataReader reader) where T : class, new()
		{
			return FillList<T>(reader).ToArray();
		}
		/// <summary>
		/// 用DataReader填充类型T的实例集
		/// </summary>
		/// <typeparam name="T">实体类型</typeparam>
		/// <param name="reader">只进结果集流</param>
		/// <returns>类型T的实例集</returns>
		public static List<T> FillList<T>(IDataReader reader) where T : class, new()
		{
			PropertyInfo[] pis = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
			string[] fields = getRecordFields(reader);
			List<T> EntityList = new List<T>();
			while (reader.Read())
			{
				T entity = FillRecord<T>(pis, reader, fields);
				EntityList.Add(entity);
			}
			return EntityList;
		}
		/// <summary>
		/// 用单行DataReader记录填充单个类型T的实例；
		/// //类型T中的公共属性名要求与DataReader中的字段名相同
		/// </summary>
		/// <typeparam name="T">实体类型</typeparam>
		/// <param name="reader">只进结果集流</param>
		/// <returns>类型T的实例</returns>
		public static T FillSinger<T>(IDataReader reader) where T : class, new()
		{
			if (reader.Read())
				return FillRecord<T>(reader);
			else
				return null;
		}
		private static T FillRecord<T>(IDataRecord record) where T : class, new()
		{
			PropertyInfo[] pis = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
			string[] fields = getRecordFields(record);
			return FillRecord<T>(pis, record, fields);
		}
		private static T FillRecord<T>(PropertyInfo[] pis, IDataRecord record, string[] fields) where T : class, new()
		{
			T entity = Activator.CreateInstance<T>();
			FillEntity(ref entity, typeof(T), pis, record, fields);
			return entity;
		}
		private static void FillEntity<T>(ref T entity, Type type, PropertyInfo[] pis, IDataRecord record, string[] fields)
		{
			foreach (PropertyInfo pi in pis)
			{
				if (Array.IndexOf(fields, pi.Name.ToLower()) != -1 && record[pi.Name] != DBNull.Value)
				{
					pi.SetValue(entity, record[pi.Name], null);
				}
			}
			if (typeof(object) != type.BaseType)
			{
				FillEntity<T>(ref  entity, type.BaseType, pis, record, fields);
			}
		}
		private static string[] getRecordFields(IDataRecord record)
		{
			string[] fields = new string[record.FieldCount];
			for (int i = 0; i < fields.Length; i++)
			{
				fields[i] = record.GetName(i).ToLower();
			}
			return fields;
		}


		private DataHelper() { }
	}
}
